/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.kramerius.fedoraaccess.rest;

import cz.mzk.kramerius.fedoraaccess.FedoraServer;
import com.google.gwt.user.server.Base64Utils;
import cz.mzk.rehan.commons.Dom4jUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;

/**
 *
 * @author Martin Řehánek <rehan at mzk.cz>
 */
class HttpConnector {

    protected static final Map<String, String> prefixNamespaceMap = new HashMap<String, String>();
    private static final Logger logger = Logger.getLogger(HttpConnector.class.getName());
    private final FedoraServer fedoraServer;
    private final HttpMethod method;

    public HttpConnector(FedoraServer fedoraServer, HttpMethod method) {
        this.fedoraServer = fedoraServer;
        this.method = method;
    }

    public Document processRequestWithXmlResult(String request) throws IOException, DocumentException {
        InputStream inputStream = createInputStream(request);
        return Dom4jUtils.loadDocument(inputStream, false);
    }

    public String processRequestWithStringResult(String request) throws IOException {
//        URLConnection uc = openConnection(request);
//        ((HttpURLConnection) uc).setRequestMethod(method.toString());
//        uc.connect();
//        return "";
        InputStream inputStream = createInputStream(request);
        return streamToString(inputStream);
    }

    public String processRequestWithStringResult(String request, Document body) throws IOException {
        String content = body.asXML();
        InputStream inputStream = createInputStream(request, content);
        return streamToString(inputStream);
    }

    private InputStream createInputStream(String request) throws IOException {
        HttpURLConnection uc = (HttpURLConnection) openConnection(request);
        uc.setRequestMethod(method.toString());
        try {
            return uc.getInputStream();
        } catch (IOException e) {
            InputStream errorStream = uc.getErrorStream();
            logger.log(Level.SEVERE, streamToString(errorStream));
            throw e;
        }
    }

    private InputStream createInputStream(String request, String content) throws IOException {
        HttpURLConnection uc = (HttpURLConnection) openConnection(request);
        uc.setRequestMethod(method.toString());
        uc.setDoOutput(true);
        uc.setRequestProperty("Content-Type", "text/xml");
        Writer out = new OutputStreamWriter(uc.getOutputStream());
        out.write(content);
        out.close();
        try {
            return uc.getInputStream();
        } catch (IOException e) {
            InputStream errorStream = uc.getErrorStream();
            System.err.println(streamToString(errorStream));
            throw e;
        }
    }

    private URLConnection openConnection(String request) throws MalformedURLException, IOException {
        URL url = new URL(request);
        String creditentials = buildCreditentials();
        String encoded = Base64Utils.toBase64(creditentials.getBytes());
        URLConnection uc = url.openConnection();
        uc.setRequestProperty("Authorization", "Basic " + encoded);
        return uc;
    }

    private String buildCreditentials() {
        StringBuilder result = new StringBuilder(3);
        result.append(fedoraServer.getLogin());
        result.append(':');
        result.append(fedoraServer.getPassword());
        return result.toString();
    }

    private String streamToString(InputStream is) throws IOException {
        if (is != null) {
            Writer writer = new StringWriter();
            char[] buffer = new char[1024];
            try {
                Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                int charsRead;
                while ((charsRead = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, charsRead);
                }
            } finally {
                is.close();
            }
            return writer.toString();
        } else {
            return "";
        }
    }

    public String getBaseUrl() {
        return fedoraServer.getUrl();
    }
}
